#include "SubsystemEggBlockBehavior.h"
#include "Subsystems/SubsystemAnimalEntities.h"

#include "GameSingleton.h"
#include "GameRandom.hpp"
#include "GameRegistry.hpp"

#include "Components/ComponentPlayer.h"
#include "Components/ComponentBody.h"
#include "Player/PlayerData.h"
#include "Log.h"
#include "Blocks/EggBlock.h"
#include "Managers/EntityManager.h"
#include "Managers/BlocksManager.h"


namespace PocketSurvival
{
    bool SubsystemEggBlockBehavior::onHitAsProjectile(std::shared_ptr<CellFace> cellFace, ComponentBody *componentBody, WorldItem *worldItem)
    {
        int32_t eggData = Terrain::ExtractData(worldItem->value);
        bool isCooked = EggBlock::GetIsCooked(eggData);
        bool isLaid = EggBlock::GetIsLaid(eggData);
        std::shared_ptr<PlayerData> playerData = nullptr;

        entt::entity owner = ((Projectile*)worldItem)->ownerEntity;
        if(owner != entt::null && GameSingleton::gameRegistry->valid(owner))
        {
            ComponentPlayer **componentPlayerPtr = GameSingleton::gameRegistry->try_get<ComponentPlayer *>(owner);
            if(componentPlayerPtr != nullptr)
            {
                playerData = (*componentPlayerPtr)->playerData;
            }
        }

        if(isCooked == false && (GameSingleton::gameRandom->getBool((isLaid ? 0.15f : 1.0f)) || (playerData != nullptr && playerData->gameMode == GameMode::Creative)))
        {
            m_subsystemAnimalEntities->animalLock.lock();
            const std::set<entt::entity> &animalEntitiesSet = m_subsystemAnimalEntities->getAnimalEntitySet();
            if (animalEntitiesSet.size() < 100)
            {
                const EggType &eggType = m_eggBlock->getEggType(eggData);
                m_subsystemAnimalEntities->addAnimalEntity(eggType.entityName, worldItem->position);
            }
            else
            {
                Log::Warn(fmt::format("动物数量超过100"));
            }
            m_subsystemAnimalEntities->animalLock.unlock();
        }
        return true;
    }

    void SubsystemEggBlockBehavior::load(const nlohmann::json &json)
    {
        m_subsystemAnimalEntities = GameSingleton::singletonPtr->getSingleton<SubsystemAnimalEntities>();
        m_eggBlock = GameSingleton::singletonPtr->getSingleton<BlocksManager>()->blocks[EggBlock::Index()]->asBlock<EggBlock*>();
    }

    static const std::string subsystemName = "EggBlockBehavior";
    const std::string &SubsystemEggBlockBehavior::getName() const
    {
        return subsystemName;
    }
}
